#include <iostream>
#include <vector>
#include <cstring>
using namespace std;

const int maxN = 101;
int g[maxN][maxN];
int N;  // vertex numbers.
int numofav; 
int alreadyVisit[maxN];
int alreadyindex = 0;
int edge[maxN];
int edgeindex = 0;

void Prime()
{
	vector<int>	visited;
	vector<int> unvisited;
	visited.reserve(N);
	unvisited.reserve(N);
	int mincost = 1 << 30;
	int vertextoadd;
	int fromvertex;
	bool flag;

	for (int i = 0; i < alreadyindex; i++)
		visited.push_back(alreadyVisit[i] - 1);	

	if (alreadyindex == 0){ 
		alreadyVisit[alreadyindex++] = 1;
		visited.push_back(0);
	}
	for (int i = 0; i < N; i++) {
		flag = true;
		for (int j = 0; j < alreadyindex; j++)
			if ( i+1 == alreadyVisit[j]) {
				flag = false;
				break;
			}
		if (flag)
			unvisited.push_back(i);
	}
	while (visited.size() != N) {
		for (int i = 0; i < visited.size(); i++){ // find the minmum cost.
			for (int j = 0; j < unvisited.size(); j++) {
				if (g[visited[i]][unvisited[j]] && g[visited[i]][unvisited[j]]< mincost) {
					mincost = g[visited[i]][unvisited[j]];
					vertextoadd = unvisited[j];	
					fromvertex = visited[i];
				}	
			} /// for~ 
		} /// for~	
		visited.push_back(vertextoadd);
		edge[edgeindex++] = g[fromvertex][vertextoadd];
		// delete the vertex from unvisited vector.
		vector<int>::iterator pos;
		for (pos = unvisited.begin(); pos < unvisited.end(); pos++)
			if (*pos == vertextoadd){
				unvisited.erase(pos);
				break;
			}
	} /// while~
}

int main()
{
	while (cin >> N) {
		alreadyindex = 0;
		edgeindex = 0;
		memset(alreadyVisit, 0, sizeof(alreadyVisit));
		memset(edge, 0, sizeof(edge));
		for (int i = 0; i < N; i++) {
			for (int j = 0; j < N; j++) {
				cin >> g[i][j];	
			}
		}
		cin >> numofav;
		for (int i = 0; i < numofav; i++) {
			int k, j;
			g[i][j] = g[j][i] = 0;
		}
		Prime();
		for (int i = 0; i < edgeindex; i++) {
			cout << edge[i] << '\t';	
		}
		if (edgeindex == 0)
			cout << 0;
		cout << endl;
	}
	return 0;
}
